import base64
import numpy as np
from PIL import Image
import io
import ddddocr

def base64_decode(str):
    return base64.b64decode(str)

def slider_puzzle_qg(p_puzzle_path: str = ''):
    """
    将小拼图去除透明边缘，返回处理后的base64图片和位置信息
    """
    image = Image.open(p_puzzle_path)
    width, height = image.size
    pixels = image.load()
    _a = 0  # 顶部透明行数
    _b = 0  # 有效拼图高度
    _c = 0  # 底部透明行数
    k = []  # 有效像素
    buffered = io.BytesIO()
    for x in range(height):
        data_pixel = []
        for y in range(width):
            r, g, b, a = pixels[y, x]
            data_pixel += [(r, g, b, a)]
        NumPy_data_pixel = np.array(data_pixel)
        if np.all(NumPy_data_pixel == 0):
            if _b == 0:
                _a += 1
            else:
                if _c == 0:
                    new_image = Image.new('RGBA', (width, _b), color=(0, 0, 0, 0))
                    new_image.putdata(k)
                    new_image.save(buffered, format="PNG")
                _c += 1
        else:
            _b += 1
            k += data_pixel
    return {
        '最顶层-顶层距离': _a,
        '中间层-拼图的高度': _b,
        '最底层-底层距离': _c,
        'base64': base64.b64encode(buffered.getvalue()).decode()
    }

def background_cutting(b_puzzle_path: str = '', b_size_h: int = 0, p_size_h: int = 0):
    """
    按小拼图的高度切割背景图，返回base64
    """
    image = Image.open(b_puzzle_path)
    width, height = image.size
    left, right = 0, width
    top, bottom = b_size_h, b_size_h + p_size_h
    cropped_image = image.crop((left, top, right, bottom))
    buffered = io.BytesIO()
    cropped_image.save(buffered, format="PNG")
    return {'base64': base64.b64encode(buffered.getvalue()).decode()}

def recognize_slider_distance(xiaopintu_path, beijingtu_path):
    """
    识别滑块需要移动的距离
    :param xiaopintu_path: 小拼图路径
    :param beijingtu_path: 背景图路径
    :return: 滑动距离
    """
    det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
    xiaopintu_data = slider_puzzle_qg(p_puzzle_path=xiaopintu_path)
    beijingtu_data = background_cutting(b_puzzle_path=beijingtu_path, b_size_h=xiaopintu_data['最顶层-顶层距离'],
                                        p_size_h=xiaopintu_data['中间层-拼图的高度'])
    res1 = det.slide_match(base64_decode(beijingtu_data['base64']), base64_decode(xiaopintu_data['base64']),
                           simple_target=True)
    res1 = res1['target'][0]
    # 为了更像人类操作，可以加一点偏移
    res = res1 * 1.1 - 4
    return res

